package cn.sciento.farm.devicemanager.service;


import cn.sciento.farm.devicemanager.common.constant.DeviceConstant;
import cn.sciento.farm.devicemanager.common.constant.ResultConstant;
import cn.sciento.farm.devicemanager.dao.entity.DevController;
import cn.sciento.farm.devicemanager.dao.entity.DevDevice;
import cn.sciento.farm.devicemanager.dao.entity.DevInverter;
import cn.sciento.farm.devicemanager.dao.entity.DevScene;
import cn.sciento.farm.devicemanager.gateway.downlink.DelayManager;
import cn.sciento.farm.devicemanager.gateway.downlink.MqttDataFactory;
import cn.sciento.farm.devicemanager.gateway.downlink.MqttTaskFactory;
import cn.sciento.farm.devicemanager.gateway.downlink.service.MqttBlockedSendManager;
import cn.sciento.farm.devicemanager.gateway.downlink.service.impl.MqttSendService;
import cn.sciento.farm.devicemanager.gateway.model.downlink.BaseBlockControlData;
import cn.sciento.farm.devicemanager.gateway.model.downlink.InverterControlData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class DeviceControlService {

    @Autowired
    private ControllerService controllerService;

    @Autowired
    private SceneService sceneService;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private InverterService inverterService;

    @Autowired
    private MqttBlockedSendManager mqttBlockedSendManager;

    @Autowired
    private MqttSendService mqttSendService;


    public int sendBlockControl(Long deviceId, int action) {
        return sendBlockControl(deviceId, action,0);
    }

    public int sendBlockControl(Long deviceId, int action, int duration) {
        DevController deviceSwitch = controllerService.getById(deviceId);
        if (deviceSwitch == null) {
            return ResultConstant.DEVICE_NOT_EXIST.getCode();
        }
//        if (deviceSwitch.getOnline() == 0) {
//            return ResultConstant.DEVICE_OFFLINE.getCode();
//        }
        long relatedId = deviceSwitch.getRelatedEquip();
        int count = 0;
        duration = duration > 0 ? duration : (deviceSwitch.getDuration() == null ? 0 : deviceSwitch.getDuration());
        if (relatedId > 0) {
            DevController relatedSwitch = controllerService.getById(relatedId);

            //关联设备开关
            if (relatedSwitch != null) {
                if(action == DeviceConstant.CONTROL_REVERSE && deviceSwitch.getStatus() == DeviceConstant.CONTROL_FORWARD){
                    return ResultConstant.SWITCH_FORWARE_REVERSE.getCode();
                }else if(action == DeviceConstant.CONTROL_FORWARD
                        && relatedSwitch.getStatus() == DeviceConstant.CONTROL_FORWARD
                ){
                    return ResultConstant.SWITCH_FORWARE_REVERSE.getCode();
                }
                BaseBlockControlData relateMqttSendData = MqttDataFactory.getMqttDataFactory().createData(relatedSwitch.getProtocol(), MqttDataFactory.BLOCK_CONTROL);

//                duration = deviceSwitch.getDuration() == null ? 0 : deviceSwitch.getDuration();
                relateMqttSendData.setCircuit(relatedSwitch.getCircuit());
                relateMqttSendData.setConcentrator(relatedSwitch.getEui());
                relateMqttSendData.setNode(relatedSwitch.getNode());
                relateMqttSendData.setEn(action == 2 ? 1 : 0);
                relateMqttSendData.setDuration(duration);
                mqttSendService.send(relateMqttSendData.generate());
            }
        }
        BaseBlockControlData abstractBlockData = MqttDataFactory.getMqttDataFactory().createData(deviceSwitch.getProtocol(), MqttDataFactory.BLOCK_CONTROL);
//        duration = deviceSwitch.getDuration() == null ? 0 : deviceSwitch.getDuration();
        abstractBlockData.setCircuit(deviceSwitch.getCircuit());
        abstractBlockData.setConcentrator(deviceSwitch.getEui());
        abstractBlockData.setNode(deviceSwitch.getNode());
        abstractBlockData.setEn(action == 2 ? 0 : action);
        abstractBlockData.setDuration(duration);
        count = mqttBlockedSendManager.send(abstractBlockData).getCode();
//        saveSwitchLog(deviceSwitch, count, action, duration);
        return count;
    }

    public int sendSwitchControl(DevController deviceSwitch,int action){
        return sendSwitchControl(deviceSwitch,action,0);
    }

    public int sendSwitchControl(DevController deviceSwitch,int action,int delay){
        BaseBlockControlData abstractBlockData = MqttDataFactory.getMqttDataFactory().createData(deviceSwitch.getProtocol(), MqttDataFactory.SIMPLE_CONTROL);
        int duration = deviceSwitch.getDuration() == null ? 0 : deviceSwitch.getDuration();
        abstractBlockData.setCircuit(deviceSwitch.getCircuit());
        abstractBlockData.setConcentrator(deviceSwitch.getEui());
        abstractBlockData.setNode(deviceSwitch.getNode());
        abstractBlockData.setEn(action == 2 ? 0 : action);
        abstractBlockData.setDuration(duration);
        DelayManager.getInstance().executeLog(MqttTaskFactory.sendDefault(
                abstractBlockData.generate()
        ), delay);
//        saveSwitchLog(deviceSwitch, DeviceConstant.RESULT_UNKNOWN, action, duration);
        return 1;
    }

    public int controlScene(long sceneId, int action) {
        DevScene deviceScene = sceneService.getById(sceneId);
        if (deviceScene == null) {
            return ResultConstant.NULL_PARAMETER.getCode();
        }
        String type = deviceScene.getType();
        if(type.equals(DeviceConstant.SCENE_TYPE_IRRIGATION) && action > 0){
            int result = handleStrategy(deviceScene);
            if(result != ResultConstant.SUCCESS.getCode()){
                return result;
            }
        }
        int count =  sendSceneControl(deviceScene,action);
        // 修改场景的状态
        if(action >0){
            if(count >0){
                deviceScene.setStatus(action);
                deviceScene.setLastTime(System.currentTimeMillis());
                sceneService.updateById(deviceScene);
            }
        }else if(action == 0) {
            deviceScene.setStatus(action);
            sceneService.updateById(deviceScene);
//            DeviceSceneLog deviceSceneLog = new DeviceSceneLog();
//            deviceSceneLog.setSceneId(deviceScene.getId());
//            deviceSceneLog.setStartTime(deviceScene.getLastTime());
//            int duration = (int)(System.currentTimeMillis() - deviceScene.getLastTime());
//            deviceSceneLog.setDuration(duration);
//            deviceSceneLogService.add(deviceSceneLog);
        }
        return count;
    }

    private int sendSceneControl(DevScene deviceScene,int action)  {
        List<DevDevice> deviceConcentratorList = sceneService.getDeviceById(deviceScene.getId());
        List<DevController> deviceSwitchList = new LinkedList<>();
        for(DevDevice deviceConcentrator : deviceConcentratorList){
            List<DevController> switcheList = controllerService.getByEui(deviceConcentrator.getId());
            deviceSwitchList.addAll(switcheList);
        }
        int count = 0;
        for(int  i = 0;i< deviceSwitchList.size();i++ ){
            DevController deviceSwitch = deviceSwitchList.get(i);
            count += sendSwitchControl(deviceSwitch,action,i*1);

        }
        return count;
    }

    private Integer handleStrategy(DevScene deviceScene) {
        int pressureResult = setInverterPressure(deviceScene);
        String strategy = deviceScene.getStrategy();
        if(strategy.equals(DeviceConstant.SCENE_STRATE_INTERRUPT)){
            if(pressureResult != ResultConstant.SUCCESS.getCode()){
                return pressureResult;
            }

        }else if(strategy.equals(DeviceConstant.SCENE_STRATE_IGNORE)){
            return ResultConstant.SUCCESS.getCode();
        }else if(strategy.equals(DeviceConstant.SCENE_STRATE_AGAIN)){
            if(pressureResult != ResultConstant.SUCCESS.getCode()){
                pressureResult = setInverterPressure(deviceScene);
                if(pressureResult != ResultConstant.SUCCESS.getCode()){
                    return pressureResult;
                }
            }

        }else {
            return ResultConstant.FAILED.getCode();
        }
        return ResultConstant.SUCCESS.getCode();
    }

    private int setInverterPressure(DevScene deviceScene) {
        Long inverterId = deviceScene.getInverterId();
        if(inverterId == null){
            return ResultConstant.NOT_SET_INVERTER.getCode();
        }
        DevInverter deviceInverter = inverterService.getById(inverterId);
        if(deviceInverter == null){
            return ResultConstant.NOT_SET_INVERTER.getCode();
        }
        InverterControlData inverterControlData = new InverterControlData();
        inverterControlData.setEui(deviceInverter.getEui());
        inverterControlData.setId(deviceInverter.getAddr());
        inverterControlData.setGivenPress(deviceScene.getDefaultValue());
        int result = mqttBlockedSendManager.send(inverterControlData,8*1000).getCode();
        if(result != ResultConstant.SUCCESS.getCode()){
            return ResultConstant.SET_PRESSURE_FAILURE.getCode();
        }
        return result;
    }

    public int controlSceneSwitch(long controllerId, int action) {
        DevController deviceSwitch = controllerService.getById(controllerId);
        if(deviceSwitch == null){
            return ResultConstant.NULL_PARAMETER.getCode();
        }
        DevDevice deviceConcentrator = deviceService.getById(deviceSwitch.getEui());
        List<DevScene> deviceSceneList = sceneService.getByDeviceId(deviceConcentrator.getId());
        deviceSceneList = deviceSceneList.stream().filter(item->{
            return item.getType().equals(DeviceConstant.SCENE_TYPE_IRRIGATION);
        }).collect(Collectors.toList());
        if(deviceSceneList.size() > 1){
            return ResultConstant.SET_MULTI_SCENE.getCode();
        }
        DevScene deviceScene = null ;
        if(deviceSceneList.size() == 1){
            deviceScene = deviceSceneList.get(0);
        }
        if(deviceScene != null){
            int result = handleStrategy(deviceScene);
            if(result == ResultConstant.SUCCESS.getCode()){
                return result;
            }
        }
        return sendBlockControl(deviceSwitch.getId(),action);
    }
}
